// 导入express框架，用于构建Web服务器和API
const express = require('express');
// 导入Node.js内置的path模块，用于处理文件路径。
const path = require('path');
// 导入Node.js模块的promisesAPI
const fs = require('fs').promises;
// 导入cors中间件，启用跨源资源共享的第三方插件，允许服务器接受不同端口的请求，前后端分离时很常见。
const cors = require('cors');

// app 是整个服务器的核心，用于定义路由（处理特定 URL 的请求）、添加中间件（处理请求的函数）以及配置服务器行为。
const app = express();
// 将 cors 中间件应用到 Express 应用程序
app.use(cors());
// 添加中间件来解析传入请求的 JSON 格式数据
app.use(express.json());
// 配置提供静态文件服务，从public中提供文件
// express.static()是一个中间件用于提供静态文件，如 HTML,CSS，js等
app.use(express.static(path.join(__dirname,'public')));

const DATA_DIR = path.join(__dirname,'data');
const DATA_FILE = path.join(DATA_DIR,'book.json');

// 定义一个名为ensureDataFile的异步函数，目的是为了确保数文件存在
async function ensureDataFile(){
  // 创建数据目录(DATA_DIR),如果目录已存在则无操作。
  await fs.mkdir(DATA_DIR,{recursive:true});
  // 尝试访问数据文件(DATA_FILE),如果文件不存在，则创建它并写入初始内容'[]'
  try{
    await fs.access(DATA_FILE);
  }catch(err){
    await fs.writeFile(DATA_FILE,'[]','utf8');
  }
}

// 定义一个名为 readData 的异步函数，用于读取和解析数据文件
async function readData() {
  // 读取 DATA_FILE 文件的内容，并将其存储为 UTF-8 编码的字符串
  const content = await fs.readFile(DATA_FILE, 'utf8');
  // 将文件内容解析为 JavaScript 对象，并返回。如果文件内容为空，则返回空数组 []。
  return JSON.parse(content || '[]');
}

// 定义一个名为writeData的异步函数，用于将数据写入文件。
async function writeData(data){
  // 将data转化为格式化的JSON字符串，并写入到DATA_FILE文件，使用UFT-8编码
  await fs.writeFile(DATA_FILE,JSON.stringify(data,null,2),'utf8')
}

// 定义一个 GET 路由，处理对 /api/books 的 HTTP GET 请求。
app.get('/api/books', async (req, res, next) => {
  // 尝试读取数据并以 JSON 格式返回，如果失败则将错误传递给错误处理中间件
  try {
    const books = await readData();
    res.json(books);
  } catch (err) { next(err); }
});

// 定义一个 GET 路由，处理对 /api/books/:id 的 HTTP GET 请求，查找特定 ID 的书籍。
app.get('/api/books/:id', async (req, res, next) => {
  
  try {
    const id = Number(req.params.id);
    const books = await readData();
    const book = books.find(b => b.id === id);
    if (!book) return res.status(404).json({ error: '找不到该图书' });
    res.json(book);
  } catch (err) { next(err); }
});

// API: 新增
app.post('/api/books', async (req, res, next) => {
  try {
    const { title, notes } = req.body;
    if (!title || typeof title !== 'string') {
      return res.status(400).json({ error: 'title 必填且为字符串' });
    }
    const books = await readData();
    // 生成 id（简单自增）
    const nextId = books.length ? Math.max(...books.map(b => b.id)) + 1 : 1;
    const newBook = { id: nextId, title: title.trim(), notes: (notes || '').trim() };
    books.push(newBook);
    await writeData(books);
    res.status(201).json(newBook);
  } catch (err) { next(err); }
});

// API: 更新
app.put('/api/books/:id', async (req, res, next) => {
  try {
    const id = Number(req.params.id);
    const { title, notes } = req.body;
    const books = await readData();
    const idx = books.findIndex(b => b.id === id);
    if (idx === -1) return res.status(404).json({ error: '找不到该图书' });
    if (title && typeof title === 'string') books[idx].title = title.trim();
    if (notes !== undefined) books[idx].notes = (notes || '').trim();
    await writeData(books);
    res.json(books[idx]);
  } catch (err) { next(err); }
});

// API: 删除
app.delete('/api/books/:id', async (req, res, next) => {
  try {
    const id = Number(req.params.id);
    const books = await readData();
    const filtered = books.filter(b => b.id !== id);
    if (filtered.length === books.length) return res.status(404).json({ error: '找不到该图书' });
    await writeData(filtered);
    res.json({ success: true });
  } catch (err) { next(err); }
});

// 错误处理中间件（简单打印）
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: '服务器内部错误' });
});

const PORT = process.env.PORT || 3000;
ensureDataFile()
  .then(() => {
    app.listen(PORT, () => {
      console.log(`服务器已启动: http://localhost:${PORT}`);
    });
  })
  .catch(err => {
    console.error('无法创建数据文件：', err);
  });